package ex2a.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JPanel;

import ex2a.controller.Controller;
import ex2a.model.ThreadContext;

public class ThreadsPanel extends JPanel {
	private static final long serialVersionUID = 1L;

	private Controller controller = null;
	private Dimension d;
	private Rectangle2D.Double prodRect, consRect;
	
	private static final Color[] cores =
		{
			new Color(0xffff00), //BLOCKED
			new Color(0x0000ff), //NEW
			new Color(0x00ffff), //RUNNABLE
			new Color(0x0), //TERMINATED
			new Color(0x00ff00), //TIMED_WAITING
			new Color(0xff0000) //WAITING
		};
	
	public ThreadsPanel() {
		controller = Controller.getInstance();
		controller.setThreadsPanel( this );
		
		d = new Dimension();
		
		consRect = new Rectangle2D.Double();
		prodRect = new Rectangle2D.Double();
		
		setBackground( Color.WHITE );
		setForeground( Color.BLACK );
		
	}
	
	@Override
	public void paintComponent( Graphics _g ) {
		Rectangle2D.Double border = new Rectangle2D.Double();
		Graphics2D g = (Graphics2D) _g;
		ThreadContext[] prod, cons;
		double width, height, borderWidth, borderHeight;
		double paddingWidth, paddingHeight;
		int i = 0, cor = 0;
        
		prod = controller.getProducers();
		cons = controller.getConsumers();
		
		d = getSize( d );
		
		width = d.getWidth();
		height = d.getHeight();
		
		g.setColor( getBackground() );
		g.fill( new Rectangle2D.Double( 0d, 0d, width, height ) );
		g.setColor( getForeground() );
		
		paddingHeight = height / 7.0;
		paddingWidth = 0.1 * ( width / (double) ( prod.length + 1 ) );
		
		prodRect.width = 0.9 * ( width / (double) prod.length );
		prodRect.height = 2.0 * paddingHeight;
		prodRect.y = paddingHeight;
		
		borderWidth = prodRect.width * 0.1;
		borderHeight = prodRect.height * 0.1;
		
		border.y = prodRect.y + borderHeight;
		border.width = prodRect.width - 2.0 * borderWidth;
		border.height = prodRect.height - 2.0 * borderHeight;
		g.setFont( new Font("Comic Sans", Font.BOLD, (int) ( prodRect.height * 0.5 ) ) );
		
		for( i = 0; i < prod.length; ++i ) {
			prodRect.x = ( i * prodRect.width + ( i + 1 ) * paddingWidth );
			border.x = prodRect.x + borderWidth;
			
			g.setColor( Color.GRAY );
			g.fill( prodRect );
			
			switch( prod[ i ].state ) {
				case BLOCKED: cor = 0; break;
				case NEW: cor = 1; break;
				case RUNNABLE: cor = 2; break;
				case TERMINATED: cor = 3; break;
				case TIMED_WAITING: cor = 4; break;
				case WAITING: cor = 5; break;
			}
			
			g.setColor( cores[cor] );
			
			g.fill( border );
			
			g.setColor( Color.BLACK );
			
			g.drawString( "P" + i, (float) border.x, (float) border.y );
			
			if( cor == 3 ) {
				g.setColor( Color.WHITE );
			}
			
			if( prod[ i ].semaphoreIndex != -1 ) {
				g.drawString( Integer.toString( prod[ i ].semaphoreIndex ), (float)border.getCenterX(), (float)( border.getCenterY() + border.height / 4 ) );
			}
		}
		
		paddingWidth = 0.1 * ( width / (double) ( cons.length + 1 ) );
		
		consRect.width = 0.9 * ( width / (double) ( cons.length ) );
		consRect.height = 2.0 * paddingHeight;
		consRect.y = 4.0 * paddingHeight;
		
		borderWidth = consRect.width * 0.1;
		borderHeight = consRect.height * 0.1;
		
		border.y = consRect.y + borderHeight;
		border.width = consRect.width - 2.0 * borderWidth;
		border.height = consRect.height - 2.0 * borderHeight;
		
		g.setFont( new Font("Comic Sans", Font.BOLD, (int) ( consRect.height * 0.5 ) ) );
		
		for( i = 0; i < cons.length; ++i ) {
			consRect.x = ( i * consRect.width + ( i + 1 ) * paddingWidth );
			border.x = consRect.x + borderWidth;
			
			g.setColor( Color.GRAY );
			g.fill( consRect );
			
			switch( cons[ i ].state ) {
				case BLOCKED: cor = 0; break;
				case NEW: cor = 1; break;
				case RUNNABLE: cor = 2; break;
				case TERMINATED: cor = 3; break;
				case TIMED_WAITING: cor = 4; break;
				case WAITING: cor = 5; break;
			}
			
			g.setColor( cores[cor] );
			
			g.fill( border );
			
			g.setColor( Color.BLACK );
			
			g.drawString( "C" + i, (float) consRect.x, (float) consRect.y );
			
			if( cor == 3 ) {
				g.setColor( Color.WHITE );
			}
			
			if( cons[ i ].semaphoreIndex != -1 ) {
				g.drawString( Integer.toString( cons[ i ].semaphoreIndex ), (float)border.getCenterX(), (float)( border.getCenterY() + border.height / 4 ) );
			}
		}
	}
	
}
